home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Applications
/
PICSee Dust 1.01
/
Primary Source
/
PICSViewer.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-03
|
49KB
|
1,757 lines
#include "PICSViewer.h"
#include "PICSViewerPrivate.h"
#include "PICS_Operations.h"
#include "PICS_Utils.h"
#include "CropPICTs.h" // For CapturePICT()
#include "PICSCompositeDialog.h" // For SetupCompositeDialog()
#include "PICS_Split.h"
#include "Class_ProgressWindow.h"
#include "GrayDraw 3D.h"
#include "Class_DynamoArray.cpp"
#include "FileRegistry.h"
#include "MovableModalDialogs.h"
#include "SimpleError.h"
#include "QDUtils.h"
#include "Monitors.h"
#include "TimerUtils.h"
#include "KeyUtils.h"
#include "assert_mac.h"
#include "main.h" // For AppEmergencyUpdate()
// ---------------------------------------------------------------------------
static DynamoArray<PICSViewerData*> sViewerList;
static struct {
short changeCreator;
short animationMethod;
short appFileRefNum;
long minFileSize;
} sPICSViewer;
// ---------------------------------------------------------------------------
void InitPICSViewer(Boolean changeCreator, short animationMethod, RGBColor *marqueeColor) {
PicHandle btnPic;
Rect drawRect;
Rect bufferBounds;
Rect monitorBounds;
GWorldPtr saveWorld;
GDHandle saveDev;
sPICSViewer.changeCreator = changeCreator;
SetPICSViewerAnimationMethod(animationMethod);
SetPICSViewerMarqueeColor(marqueeColor);
sPICSViewer.appFileRefNum = CurResFile();
btnPic = (PicHandle)Get1Resource('PICT', kPICSViewer_StopBtnUpID);
sBtnData.bounds = (**btnPic).picFrame;
FlushRectTopLeft(&sBtnData.bounds);
bufferBounds = sBtnData.bounds;
bufferBounds.right = (kPICSViewer_ForwardBtn-kPICSViewer_StopBtn+1) *
bufferBounds.right;
bufferBounds.bottom += bufferBounds.bottom;
GetGWorld(&saveWorld, &saveDev);
monitorBounds = (**GetDeepestDevice()).gdRect;
CenterRect(&bufferBounds, &monitorBounds);
GBErr err;
/*
err = NewGraphicsBuffer(&sBtnData.buffer, 0,
(CP_Rect*)&bufferBounds, kGBOptimalFlag, 0);
FlushRectTopLeft(&bufferBounds);
*/
FlushRectTopLeft(&bufferBounds);
err = NewGraphicsBuffer(&sBtnData.buffer, 8,
(CP_Rect*)&bufferBounds, kGBOptimalFlag, 0);
SetGraphicsBuffer(sBtnData.buffer);
short i;
for (i = kPICSViewer_StopBtnUpID; i <= kPICSViewer_ForwardBtnUpID; i++) {
btnPic = (PicHandle)Get1Resource('PICT', i);
drawRect = sBtnData.bounds;
OffsetRect(&drawRect, drawRect.right * (i-kPICSViewer_StopBtnUpID), 0);
DrawPicture(btnPic, &drawRect);
ReleaseResource((Handle)btnPic);
}
for (i = kPICSViewer_StopBtnDownID; i <= kPICSViewer_ForwardBtnDownID; i++) {
btnPic = (PicHandle)Get1Resource('PICT', i);
drawRect = sBtnData.bounds;
OffsetRect(&drawRect, drawRect.right * (i-kPICSViewer_StopBtnDownID),
drawRect.bottom);
DrawPicture(btnPic, &drawRect);
ReleaseResource((Handle)btnPic);
}
SetGWorld(saveWorld, saveDev);
} // END InitPICSViewer
// ---------------------------------------------------------------------------
void SetPICSViewerAnimationMethod(short animationMethod) {
sPICSViewer.animationMethod = animationMethod;
} // END SetPICSViewerAnimationMethod
void SetPICSViewerMarqueeColor(RGBColor *marqueeColor) {
_SetMarqueeColor(marqueeColor);
} // END SetPICSViewerMarqueeColor
void SetPICSViewerOpenProgress(short minFileSizeToShow) {
sPICSViewer.minFileSize = minFileSizeToShow;
} // END SetPICSViewerOpenProgress
// ---------------------------------------------------------------------------
void CleanupPICSViewer() {
if (sBtnData.buffer != NULL) {
DisposeGraphicsBuffer(sBtnData.buffer);
}
} // END CleanupPICSViewer
// ---------------------------------------------------------------------------
void _DrawPICSViewerBtn(PICSViewerData *viewer, short btn, Boolean pushed) {
Rect srcRect, destRect;
short offset = btn - kPICSViewer_StopBtn;
RGBColor saveBack, backColor;
GetBackColor(&saveBack);
backColor.red = backColor.green = backColor.blue = 0xFFFF;
RGBBackColor(&backColor);
srcRect = sBtnData.bounds;
OffsetRect(&srcRect, srcRect.right * offset, pushed ? srcRect.bottom : 0);
GetDItemRect(viewer->window, btn, &destRect);
CopyGraphicsBuffer2Window(sBtnData.buffer, viewer->window,
(CP_Rect*)&srcRect, (CP_Rect*)&destRect);
RGBBackColor(&saveBack);
} // END DrawPICSViewerBtn
// ---------------------------------------------------------------------------
PICSViewerData *_ExtractPICSViewer(DialogPtr srcViewer) {
if (srcViewer != NULL) {
return((PICSViewerData*)GetWRefCon(srcViewer));
}
else
return(NULL);
} // END ExtractPICSViewer
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
DialogPtr GetCurrentPICSViewer() {
DialogPtr topWindow = FrontWindow();
while (topWindow != NULL) {
if (GetWindowKind(topWindow) == dialogKind &&
!IsMovableModal(topWindow)) {
PICSViewerData *viewer;
viewer = _ExtractPICSViewer(topWindow);
ASSERT(viewer != NULL);
return(viewer->window);
}
topWindow = GetNextWindow(topWindow);
}
return(NULL);
} // END GetCurrentPICSViewer
Boolean IsPICSViewer(DialogPtr viewer) {
PICSViewerData *realViewer;
realViewer = _ExtractPICSViewer(viewer);
if (realViewer == NULL)
return(false);
if (sViewerList.Search(realViewer) != kDynamoArrayOutOfBoundsErr)
return(true);
else
return(false);
} // END IsPICSViewer
Boolean ClosePICSViewer(DialogPtr viewer) {
return(_ClosePICSViewer(_ExtractPICSViewer(viewer)));
}
Boolean SavePICSViewer(DialogPtr viewer) {
return(_SavePICSViewer(_ExtractPICSViewer(viewer)));
}
void ClickPICSViewer(DialogPtr viewer, short itemClicked) {
_ClickPICSViewer(_ExtractPICSViewer(viewer), itemClicked);
}
void KeyDownPICSViewer(DialogPtr viewer, char keyPressed) {
_KeyDownPICSViewer(_ExtractPICSViewer(viewer), keyPressed);
}
void UpdatePICSViewer(DialogPtr viewer) {
_UpdatePICSViewer(_ExtractPICSViewer(viewer));
}
void ActivatePICSViewer(DialogPtr viewer, Boolean activate) {
_ActivatePICSViewer(_ExtractPICSViewer(viewer), activate);
}
void IdlePICSViewer(DialogPtr viewer) {
_IdlePICSViewer(_ExtractPICSViewer(viewer));
}
Boolean IsPICSViewerModified(DialogPtr viewer) {
return(_IsPICSViewerModified(_ExtractPICSViewer(viewer)));
}
void SelectEntirePICSViewerFrame(DialogPtr viewer, Boolean select) {
_SelectEntirePICSViewerFrame(_ExtractPICSViewer(viewer), select);
}
void CopyPICSViewerFrame(DialogPtr viewer) {
_CopyPICSViewerFrame(_ExtractPICSViewer(viewer));
}
void CompositePICSViewer(DialogPtr viewer) {
_ClickPICSViewer(_ExtractPICSViewer(viewer), kPICSViewer_CompositeBtn);
} // END CompositePICSViewer
void SplitPICSViewer(DialogPtr viewer) {
_ClickPICSViewer(_ExtractPICSViewer(viewer), kPICSViewer_SplitBtn);
} // END SplitPICSViewer
// ---------------------------------------------------------------------------
void NewPICSViewer(FSSpec *picsFile) {
PICSViewerData *viewer;
// Get a PICS file first
FSSpec fileToOpen;
if (picsFile == NULL) {
if (!OpenPICSFile(&fileToOpen))
return;
}
else {
fileToOpen = *picsFile;
// Make sure it's a PICS file...
FInfo fileInfo;
OSErr myErr;
myErr = FSpGetFInfo(&fileToOpen, &fileInfo);
if (fileInfo.fdType == kPICTFileType) {
SimpleError(kAlertErrID, kErrMsgID, kDontAcceptPICTFileErrMsg);
return;
}
}
viewer = (PICSViewerData*)NewPtr(sizeof(PICSViewerData));
ASSERT(viewer != NULL);
// Copy file spec of the PICS file to open
viewer->picsFile = fileToOpen;
// Time to load 'em in
PicHandle thePic;
Rect bufferBounds;
Rect monitorBounds;
GWorldPtr saveWorld;
GDHandle saveDev;
SetCursor(*GetCursor(watchCursor));
// -------------------------
// OPEN PICS FILE
// -------------------------
viewer->fileRefNum =
FSpOpenResFile(&viewer->picsFile, fsRdWrPerm); // Exclusive read/write since we'll
// keep it open for the duration...
if (viewer->fileRefNum == -1) {
SimpleError(kAlertErrID, kErrMsgID, kCantOpenFileErrMsg);
DisposePtr((Ptr)viewer);
return;
}
if (!RegisterFile(viewer->fileRefNum)) {
// File already opened by us. Find it and select it.
WindowPtr theWindow = FrontWindow();
Boolean foundWindow = false;
while (theWindow != NULL) {
if (IsPICSViewer(theWindow)) {
PICSViewerData *theViewer = _ExtractPICSViewer(theWindow);
if (theViewer->fileRefNum == viewer->fileRefNum) {
SelectWindow(theViewer->window);
foundWindow = true;
}
}
if (!foundWindow)
theWindow = GetNextWindow(theWindow);
else
theWindow = NULL;
}
DisposePtr((Ptr)viewer);
UseResFile(sPICSViewer.appFileRefNum);
return;
}
// Send update event
AppEmergencyUpdate();
UseResFile(viewer->fileRefNum);
// ----------------------------------
// DETERMINE WHICH MONITOR TO USE
// ----------------------------------
GDHandle outputDevice = GetDeepestDevice();
short monitorDepth = GetDeviceDepth(outputDevice);
short bufferDepth;
GetGWorld(&saveWorld, &saveDev);
monitorBounds = (**outputDevice).gdRect;
// ----------------------------------
// SETUP PROGRESS WINDOW
// ----------------------------------
Boolean doProgress;
ProgressWindow *progressWindow = NULL;
short increment;
long fileSize;
doProgress = false;
if (sPICSViewer.minFileSize == kAlwaysShowOpenProgress) {
doProgress = true;
}
else if (sPICSViewer.minFileSize > 0) {
(void)GetEOF(viewer->fileRefNum, &fileSize);
// minFileSize is in Kbytes, fileSize is in bytes
if ((fileSize/1024) >= sPICSViewer.minFileSize)
doProgress = true;
}
if (doProgress) {
progressWindow = new ProgressWindow(outputDevice, 100);
SetPort(progressWindow->GetWindow());
TextFont(geneva);
TextSize(9);
TextFace(bold);
}
// -------------------------
// GET NUMBER OF FRAMES
// -------------------------
if (doProgress) {
progressWindow->SetPrimaryMessage("\pCounting number of frames...");
}
viewer->numFrames = Count1Resources(kPICSRsrcType);
if (viewer->numFrames < 1) {
if (doProgress) {
delete progressWindow;
}
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kNoPICTsInFileErrMsg);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
DisposePtr((Ptr)viewer);
return;
}
if (doProgress) {
increment = 100 / (viewer->numFrames+6);
}
// ----------------------------------
// GET DEPTH AND AREA OF PICT
// ----------------------------------
if (doProgress) {
progressWindow->SetPrimaryMessage("\pGetting depth and boundary...");
progressWindow->IncrementBy(increment);
}
thePic = (PicHandle)Get1Resource(kPICSRsrcType, 128);
if (thePic == NULL) {
// We have picts in the file, but there isn't one
// with an id of 128! Hmm. Probably not a PICS file.
if (doProgress) {
delete progressWindow;
}
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kInvalidPICSFormatErrMsg);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
DisposePtr((Ptr)viewer);
return;
}
viewer->picsInfo.depth = GetPictDepth(thePic);
if (doProgress) {
progressWindow->IncrementBy(increment);
}
short offsetH, offsetV;
viewer->picsFrame = (**thePic).picFrame;
viewer->outputFrame = (**thePic).picFrame;
// Just in case the topLeft of the picture ISN'T (0,0), we'll
// store it for later safekeeping
offsetH = viewer->picsFrame.left;
offsetV = viewer->picsFrame.top;
// Now make it flushed topLeft (0,0)
FlushRectTopLeft(&viewer->picsFrame);
// ----------------------------------
// DETERMINE AREA OF BUFFER
// ----------------------------------
if (doProgress) {
progressWindow->SetPrimaryMessage("\pDetermining memory boundary...");
progressWindow->IncrementBy(increment);
}
bufferBounds = viewer->picsFrame;
bufferBounds.bottom = (viewer->numFrames) *
bufferBounds.bottom;
// ----------------------------------
// SETUP ANIMATION METHOD
// ----------------------------------
if (doProgress) {
progressWindow->SetPrimaryMessage("\pSetting up memory...");
progressWindow->IncrementBy(increment);
}
viewer->animationMethod = sPICSViewer.animationMethod;
if (REVERSEANIMATION_SHORTCUT) {
if (viewer->animationMethod == kUsePictureGWorldMethod)
viewer->animationMethod = kUseMonitorGWorldMethod;
else if (viewer->animationMethod == kUseMonitorGWorldMethod)
viewer->animationMethod = kUsePictureGWorldMethod;
}
if (viewer->animationMethod == kUsePictureGWorldMethod) {
// Specify an explicit depth only if depth of PICS isn't
// same as that of the screen
if (monitorDepth != viewer->picsInfo.depth) {
bufferDepth = viewer->picsInfo.depth;
// Use local coords (topleft is 0,0)
}
else {
bufferDepth = 0;
CenterRect(&bufferBounds, &monitorBounds);
// Use global coords
}
}
else if (viewer->animationMethod == kUseMonitorGWorldMethod) {
bufferDepth = 0;
CenterRect(&bufferBounds, &monitorBounds);
}
// -------------------------
// ALLOCATE GRAPHICSBUFFER
// -------------------------
if (doProgress) {
progressWindow->SetPrimaryMessage("\pAllocating memory...");
progressWindow->IncrementBy(increment);
}
GBErr err;
err = NewGraphicsBuffer(&viewer->buffer, bufferDepth,
(CP_Rect*)&bufferBounds, kGBOptimalFlag, 0);
if (err != noErr) {
if (viewer->animationMethod == kUseMonitorGWorldMethod &&
viewer->picsInfo.depth < monitorDepth &&
HasMonitorDepth(outputDevice, viewer->picsInfo.depth, true)) {
// We're using expensive method. Try less memory
// intensive kUsePictureGWorldMethod.
viewer->animationMethod = kUsePictureGWorldMethod;
bufferDepth = viewer->picsInfo.depth;
FlushRectTopLeft(&bufferBounds);
err = NewGraphicsBuffer(&viewer->buffer, bufferDepth,
(CP_Rect*)&bufferBounds, kGBOptimalFlag, 0);
if (err != noErr) {
// Aack! Still not enough memory. Oh well...
if (doProgress) {
delete progressWindow;
}
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kNoGWorldErrMsg);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
DisposePtr((Ptr)viewer);
return;
}
}
else {
if (doProgress) {
delete progressWindow;
}
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kNoGWorldErrMsg);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
DisposePtr((Ptr)viewer);
return;
}
}
FlushRectTopLeft(&bufferBounds);
if (bufferDepth != 0)
viewer->bufferDepth = bufferDepth;
else {
viewer->bufferDepth = monitorDepth;
}
// ----------------------------------
// DRAW PICTS INTO BUFFER
// ----------------------------------
if (doProgress) {
progressWindow->IncrementBy(increment);
}
short offsetAmount;
Rect drawRect;
Str15 countFrameStr;
viewer->usesDeltaPictures = false;
if (doProgress) {
progressWindow->SetPrimaryMessage("\pLoading frame:");
}
for (short i = 1, resID = kPICSRsrcStartID;
i <= viewer->numFrames; i++, resID++) {
// Set to old gworld & window port & draw message
if (doProgress) {
SetGWorld(saveWorld, saveDev);
SetPort(progressWindow->GetWindow());
NumToString(i, countFrameStr);
progressWindow->SetSecondaryMessage(countFrameStr);
}
// Set to offscreen buffer
SetGraphicsBuffer(viewer->buffer);
thePic = (PicHandle)Get1Resource(kPICSRsrcType, resID);
if (thePic == NULL) {
if (doProgress) {
delete progressWindow;
}
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kUnableLoadPICTErrMsg);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
DisposeGraphicsBuffer(viewer->buffer);
viewer->buffer = NULL;
DisposePtr((Ptr)viewer);
return;
}
/*
Here it gets tricky, because the PICS format is somewhat
"goofy": there are actually 2 ways a PICS can be made:
The first way, and the easiest, is a sequential series of
PICTs which are all the size dimensions. Very straightforward.
The second way is to have a first picture which defines
the rest of the frames. The rest of the frames are defined
by changes to the previous frame; thus they will have
different frame rects. These are called delta pictures.
[History: the PICS format is old, and memory conservation
was much more important then than now, and delta pictures
served a way to do this. However, it now complicates my
life, since one program that I use implements this method:
Cinemation. Aargh!]
We'll look for delta pictures by looking at the picture's
picFrame. If it's smaller than that of the first picture,
it's a delta picture...
*/
// Get frame of first picture
drawRect = viewer->picsFrame;
// Offset it appropriately into viewer->buffer
offsetAmount = drawRect.bottom * (i-1);
if (i > 1) {
Rect picFrame = (**thePic).picFrame;
// If first picture wasn't flushed topLeft (0,0), we
// have to do the same compensation here
OffsetRect(&picFrame, -offsetH, -offsetV);
if (picFrame.left > drawRect.left ||
picFrame.top > drawRect.top ||
picFrame.right < drawRect.right ||
picFrame.bottom < drawRect.bottom) {
// Shucks! Delta pictures...
// Copy previous frame
Rect prevFrameRect = viewer->picsFrame;
Rect curFrameRect = drawRect;
OffsetRect(&prevFrameRect, 0, prevFrameRect.bottom * (i-2));
OffsetRect(&curFrameRect, 0, offsetAmount);
CopyGraphicsBuffer(viewer->buffer, viewer->buffer,
(CP_Rect*)&prevFrameRect, (CP_Rect*)&curFrameRect);
if (VIEWDELTA_DEBUG)
FillRect(&curFrameRect, &qd.gray);
// Adjust destination rect for later DrawPicture()
// because of delta picture
drawRect = picFrame;
viewer->usesDeltaPictures = true;
}
}
OffsetRect(&drawRect, 0, offsetAmount);
DrawPicture(thePic, &drawRect);
ReleaseResource((Handle)thePic);
if (doProgress) {
SetGWorld(saveWorld, saveDev); // we have to do this otherwise progress isn't shown
SetPort(progressWindow->GetWindow());
progressWindow->IncrementBy(increment);
}
}
// ----------------------------------
// GET PICS SPEED ('INFO')
// ----------------------------------
SetGWorld(saveWorld, saveDev);
if (doProgress) {
SetPort(progressWindow->GetWindow());
progressWindow->SetPrimaryMessage("\pGetting PICS speed...");
progressWindow->SetSecondaryMessage(NULL);
}
PICSInfoRsrcHdl picsInfo;
picsInfo = GetPICSInfo();
if (picsInfo != NULL) {
viewer->picsInfo = **picsInfo;
DisposePICSInfo(picsInfo);
}
else {
// Currently the only thing we use from the PICSInfo
viewer->picsInfo.speed = kDefaultPICSSpeed;
}
SetGWorld(saveWorld, saveDev);
if (doProgress) {
SetPort(progressWindow->GetWindow());
progressWindow->SetPrimaryMessage("\pFinishing up...");
progressWindow->FinishProgress();
delete progressWindow;
FlushEvents(everyEvent, 0);
}
// ----------------------------------
// CREATE PICSVIEWER WINDOW
// ----------------------------------
UseResFile(sPICSViewer.appFileRefNum);
short dialogID = kPICSViewerTemplateID;
if (viewer->picsFrame.right > kSmallWidth ||
viewer->picsFrame.bottom > kSmallHeight ||
USELARGEWINDOW_SHORTCUT) {
dialogID = kPICSViewerTemplateID+1; // Large dialog version
}
viewer->window = GetNewDialog(dialogID, NULL, (WindowPtr)-1);
SetWTitle(viewer->window, viewer->picsFile.name);
ASSERT(viewer->window != NULL);
// Stuff reference to PICSViewer inside refcon of dialog
SetWRefCon(viewer->window, (long)viewer);
SetPort(viewer->window);
TextFont(geneva);
TextSize(9);
// ----------------------------------
// SET PICSVIEWER PARAMETERS
// ----------------------------------
Str15 speedStr;
Rect frame;
viewer->curFrame = 0;
viewer->doLoop = true;
viewer->doBounceBack = false;
viewer->trackMouse = true;
SetRect(&viewer->marqueeRect, 0, 0, 0, 0);
SetPt(&viewer->trackingPoint, 0, 0);
viewer->currentAction = kSelectionAction;
viewer->magnification = kNormalMagnification;
viewer->fileModified = false;
(void)GetEOF(viewer->fileRefNum, &viewer->fileSize);
// Make sure speed is valid (could be negative from an
// old version of 'INFO')
if (viewer->picsInfo.speed < 1) {
viewer->picsInfo.speed = kDefaultPICSSpeed;
viewer->fileModified = true;
}
NumToString(viewer->picsInfo.speed, speedStr);
SetDItemText(viewer->window, kPICSViewer_SpeedPopupBtn, speedStr);
GetDItemRect(viewer->window, kPICSViewer_OutputBox, &frame);
CenterRect(&viewer->outputFrame, &frame);
SetDlogCtlValue(viewer->window, kPICSViewer_LoopBtn, 1);
SetDlogCtlValue(viewer->window, kPICSViewer_TrackMouseBtn, 1);
// Empty out track mouse field
SetDItemText(viewer->window, kPICSViewer_TrackMouseField, kEmptyStr);
SetDItemText(viewer->window, kPICSViewer_TrackCropField, kEmptyStr);
// ----------------------------------
// WE'RE DONE!!! (ALMOST)
// ----------------------------------
sViewerList.Append(viewer); // Add viewer to list of windows
UseResFile(sPICSViewer.appFileRefNum);
// Place window appropriately, depending whether there is already
// another window present (if so, stack new window)
WindowPtr topWindow = FrontWindow();
Rect globRect;
if (topWindow == NULL) {
globRect = (**GetDeepestDevice()).gdRect;
OffsetRect(&globRect, 10, 40);
MoveWindow(viewer->window, globRect.left, globRect.top, false);
}
else {
globRect = topWindow->portRect;
SetPort(topWindow);
LocalToGlobal(&topLeft(globRect));
LocalToGlobal(&botRight(globRect));
MoveWindow(viewer->window, globRect.left + 20, globRect.top + 20, false);
}
ShowWindow(viewer->window);
SetPort(viewer->window);
SetCursor(&qd.arrow);
} // END NewPICSViewer
// ---------------------------------------------------------------------------
Boolean _ClosePICSViewer(PICSViewerData *viewer) {
ASSERT(viewer != NULL);
if (viewer == NULL)
return(false);
Boolean doSave;
if (viewer->fileModified) {
ParamText(viewer->picsFile.name, kEmptyStr, kEmptyStr, kEmptyStr);
short itemHit = Alert(kPICSViewerPromptSaveID, NULL);
switch(itemHit) {
case kPICSViewerPromptSave: doSave = true; break;
case kPICSViewerPromptCancel: return(false); break;
case kPICSViewerPromptDontSave: doSave = false; break;
}
}
SetCursor(*GetCursor(watchCursor));
if (doSave) {
(void)_SavePICSViewer(viewer);
}
HideWindow(viewer->window);
DisposeDialog(viewer->window);
viewer->window = NULL;
if (viewer->buffer != NULL) {
DisposeGraphicsBuffer(viewer->buffer);
}
SetCursor(&qd.arrow);
(void)UnregisterFile(viewer->fileRefNum);
CloseResFile(viewer->fileRefNum);
viewer->fileRefNum = -1;
UseResFile(sPICSViewer.appFileRefNum);
DisposePtr((Ptr)viewer);
sViewerList.SearchDelete(viewer); // Remove viewer from list of windows
return(true);
} // END _ClosePICSViewer
// ---------------------------------------------------------------------------
Boolean _SavePICSViewer(PICSViewerData *viewer) {
if (viewer->fileModified) {
UseResFile(viewer->fileRefNum);
PICSInfoRsrcHdl picsInfo;
picsInfo = GetPICSInfo();
if (picsInfo == NULL) {
// No PICS info exists. Create one
picsInfo = NewPICSInfoResource();
(**picsInfo).speed = viewer->picsInfo.speed;
(**picsInfo).depth = viewer->picsInfo.depth;
(**picsInfo).creatorType = kPICSiliciousCreatorType;
}
else {
if ((**picsInfo).speed != viewer->picsInfo.speed) {
// Update speed parameter
(**picsInfo).speed = viewer->picsInfo.speed;
}
}
if (!SavePICSInfo(picsInfo, true)) {
UseResFile(sPICSViewer.appFileRefNum);
SimpleError(kAlertErrID, kErrMsgID, kCantSavePICSInfoErrMsg);
UseResFile(viewer->fileRefNum);
}
DisposePICSInfo(picsInfo);
UseResFile(sPICSViewer.appFileRefNum);
if (sPICSViewer.changeCreator) {
FInfo fileInfo;
OSErr myErr;
myErr = FSpGetFInfo(&viewer->picsFile, &fileInfo);
if (myErr == noErr &&
fileInfo.fdCreator != kPICSiliciousCreatorType) {
fileInfo.fdCreator = kPICSiliciousCreatorType;
myErr = FSpSetFInfo(&viewer->picsFile, &fileInfo);
}
}
_SetPICSViewerModified(viewer, false);
}
return(true);
} // END _SavePICSViewer
// ---------------------------------------------------------------------------
void _ClickPICSViewer(PICSViewerData *viewer, short itemClicked) {
// Handle mouse in-out niceties
if (itemClicked >= kPICSViewer_StopBtn &&
itemClicked <= kPICSViewer_ForwardBtn) {
Rect btnRect;
Point mouseLoc;
GetDItemRect(viewer->window, itemClicked, &btnRect);
_DrawPICSViewerBtn(viewer, itemClicked, true);
while (StillDown()) {}
if (itemClicked != kPICSViewer_PlayBtn)
_DrawPICSViewerBtn(viewer, itemClicked, false);
SetPort(viewer->window);
GetMouse(&mouseLoc);
if (!PtInRect(mouseLoc, &btnRect)) {
if (itemClicked == kPICSViewer_PlayBtn)
_DrawPICSViewerBtn(viewer, itemClicked, false);
return;
}
}
switch(itemClicked) {
case kPICSViewer_StopBtn:
break;
case kPICSViewer_RewindBtn:
_RewindPICSViewer(viewer);
break;
case kPICSViewer_StepBackBtn:
_StepBackPICSViewer(viewer);
break;
case kPICSViewer_PlayBtn:
_PlaySynchPICSViewer(viewer);
break;
case kPICSViewer_StepForwardBtn:
_StepForwardPICSViewer(viewer);
break;
case kPICSViewer_ForwardBtn:
_ForwardPICSViewer(viewer);
break;
case kPICSViewer_SpeedField:
case kPICSViewer_SpeedPopupBtn:
MenuHandle speedMenu;
Rect popRect;
long menuResult;
Point whatsThePoint;
Str15 speedStr;
short itemToCheck;
speedMenu = GetMenu(kPICSViewerSpeedMenuID);
ASSERT(speedMenu != NULL);
InsertMenu(speedMenu, -1);
GetDItemRect(viewer->window, kPICSViewer_SpeedField, &popRect);
whatsThePoint.h = popRect.right;
whatsThePoint.v = popRect.top;
SetPort(viewer->window);
LocalToGlobal(&whatsThePoint);
// Determine which menu item to pre-checkmark, if any
itemToCheck = CountMItems(speedMenu);
for (short i = 1; i <= CountMItems(speedMenu); i++) {
GetItem(speedMenu, i, speedStr);
StringToNum(speedStr, &menuResult);
if (viewer->picsInfo.speed == menuResult) {
itemToCheck = i;
SetItemMark(speedMenu, itemToCheck, '•');
break;
}
}
menuResult = PopUpMenuSelect(speedMenu,
whatsThePoint.v, whatsThePoint.h, itemToCheck);
if (menuResult != 0) {
GetItem(speedMenu, LoWord(menuResult), speedStr);
StringToNum(speedStr, &menuResult);
// If use did change speed, mark file as modified
if (viewer->fileModified == false) {
if (viewer->picsInfo.speed != menuResult)
_SetPICSViewerModified(viewer, true);
}
viewer->picsInfo.speed = menuResult;
_UpdatePICSViewerInfo(viewer);
}
DeleteMenu(kPICSViewerTemplateID);
ReleaseResource((Handle)speedMenu);
break;
case kPICSViewer_SpeedUpBtn:
_IncreasePICSViewerSpeed(viewer);
break;
case kPICSViewer_SpeedDownBtn:
_DecreasePICSViewerSpeed(viewer);
break;
case kPICSViewer_LoopBtn:
FlipCtlValue(viewer->window, itemClicked);
viewer->doLoop = GetDlogCtlValue(viewer->window, itemClicked);
if (viewer->doLoop)
EnableDlogCtl(viewer->window, kPICSViewer_BounceBackBtn);
else
DisableDlogCtl(viewer->window, kPICSViewer_BounceBackBtn);
break;
case kPICSViewer_BounceBackBtn:
FlipCtlValue(viewer->window, itemClicked);
viewer->doBounceBack = GetDlogCtlValue(viewer->window, itemClicked);
break;
case kPICSViewer_CompositeBtn:
case kPICSViewer_SplitBtn:
if (itemClicked == kPICSViewer_CompositeBtn) {
_CompositePICSViewer(viewer);
}
else {
_SplitPICSViewer(viewer);
}
break;
case kPICSViewer_TrackMouseBtn:
FlipCtlValue(viewer->window, itemClicked);
viewer->trackMouse = GetDlogCtlValue(viewer->window, itemClicked);
if (!viewer->trackMouse) {
SetDItemText(viewer->window,
kPICSViewer_TrackMouseField, kEmptyStr);
SetDItemText(viewer->window,
kPICSViewer_TrackCropField, kEmptyStr);
// And erase the current marquee
if (!EmptyRect(&viewer->marqueeRect)) {
_EraseMarquee(viewer, NULL);
SetRect(&viewer->marqueeRect, 0, 0, 0, 0);
}
}
break;
case kPICSViewer_OutputBox:
_ActionPICSViewer(viewer);
break;
case kPICSViewer_PopupInfoBtn:
/*
case kPICSViewer_CurFrameField:
case kPICSViewer_NumFramesField:
case kPICSViewer_PICSWidthField:
case kPICSViewer_PICSHeightField:
case kPICSViewer_TrackMouseField:
case kPICSViewer_TrackCropField:
*/
//default:
_ShowPICSViewerPopupInfo(viewer);
break;
}
} // END ClickPICSViewer
// ---------------------------------------------------------------------------
enum {
kLineHeight = 12
};
void _ShowPICSViewerPopupInfo(PICSViewerData *viewer) {
Rect popRect;
Str15 numStr;
short leftCol, rightCol;
short linePos;
GetDItemRect(viewer->window, kPICSViewer_OutputBox, &popRect);
//popRect.left = popRect.right - 200;
popRect.top = popRect.bottom - 120;
popRect.right = popRect.left + 220;
SetPort(viewer->window);
OffsetRect(&popRect, 4, -4);
EraseRect(&popRect);
GrayDrawShadowBox(&popRect, NULL);
// Anim buffer depth
leftCol = popRect.left + 10;
rightCol = leftCol + 130;
linePos = popRect.top + 20;
MoveTo(leftCol, linePos);
DrawString("\pAnimation buffer depth:");
NumToString(viewer->bufferDepth, numStr);
MoveTo(rightCol, linePos);
DrawString(numStr);
DrawString("\p-bit");
// Anim buffer size
linePos += kLineHeight;
Rect animArea;
long bufferSize;
GetGraphicsBufferBounds(viewer->buffer, (CP_Rect*)&animArea);
FlushRectTopLeft(&animArea);
bufferSize = GetGraphicsBufferRowBytes(viewer->buffer) *
(animArea.bottom) / 1024;
MoveTo(leftCol, linePos);
DrawString("\pAnimation buffer size:");
MoveTo(rightCol, linePos);
NumToString(bufferSize, numStr);
DrawString(numStr);
DrawString("\pK");
// Anim method
linePos += kLineHeight;
MoveTo(leftCol, linePos);
DrawString("\pAnimation method:");
MoveTo(rightCol, linePos);
if (viewer->animationMethod == kUseMonitorGWorldMethod)
DrawString("\pMonitor depth");
else if (viewer->animationMethod == kUsePictureGWorldMethod)
DrawString("\pFile depth");
// File depth
linePos += kLineHeight + (kLineHeight/2);
MoveTo(leftCol, linePos);
DrawString("\pPICS File depth:");
NumToString(viewer->picsInfo.depth, numStr);
MoveTo(rightCol, linePos);
DrawString(numStr);
DrawString("\p-bit");
// File size
linePos += kLineHeight;
MoveTo(leftCol, linePos);
DrawString("\pPICS File size:");
NumToString(viewer->fileSize/1024, numStr);
MoveTo(rightCol, linePos);
DrawString(numStr);
DrawString("\pK");
// File creator type
linePos += kLineHeight;
MoveTo(leftCol, linePos);
DrawString("\pInternal PICS creator type:");
MoveTo(rightCol, linePos);
if ((long)viewer->picsInfo.creatorType == 0)
DrawString("\p<none>");
else {
numStr[0] = 4;
numStr[1] = ((char*)&viewer->picsInfo.creatorType)[0];
numStr[2] = ((char*)&viewer->picsInfo.creatorType)[1];
numStr[3] = ((char*)&viewer->picsInfo.creatorType)[2];
numStr[4] = ((char*)&viewer->picsInfo.creatorType)[3];
DrawString(numStr);
}
// Delta picture info
linePos += kLineHeight + (kLineHeight/2);
MoveTo(leftCol, linePos);
DrawString("\pUses delta picture method:");
MoveTo(rightCol, linePos);
if (viewer->usesDeltaPictures)
DrawString("\pYes");
else
DrawString("\pNo");
while (StillDown()) {
}
//_UpdatePICSViewer(viewer);
EraseRect(&popRect);
InvalRect(&popRect);
} // END _ShowPICSViewerPopupInfo
// ---------------------------------------------------------------------------
void _KeyDownPICSViewer(PICSViewerData *viewer, char keyPressed) {
switch(keyPressed) {
case kEscape_Key:
_ClosePICSViewer(viewer);
break;
case kDelete_Key:
break;
case kTab_Key:
_PlaySynchPICSViewer(viewer);
break;
case kLeftArrow_Key:
case kRightArrow_Key:
case kUpArrow_Key:
case kDownArrow_Key:
if (viewer->trackMouse &&
!EmptyRect(&viewer->marqueeRect) &&
!CmdKeyDown()) {
_KeyDownPICSViewerSelection(viewer, keyPressed);
}
else {
switch(keyPressed) {
case kLeftArrow_Key: _StepBackPICSViewer(viewer); break;
case kRightArrow_Key: _StepForwardPICSViewer(viewer); break;
case kUpArrow_Key: _RewindPICSViewer(viewer); break;
case kDownArrow_Key: _ForwardPICSViewer(viewer); break;
}
}
break;
} // END keyPressed
} // END _KeyDownPICSViewer
// ---------------------------------------------------------------------------
void _UpdatePICSViewer(PICSViewerData *viewer) {
GrafPtr savePort;
short i;
Str15 tempStr;
Rect frame;
short oldRefNum;
oldRefNum = CurResFile();
UseResFile(sPICSViewer.appFileRefNum);
GetPort(&savePort);
SetPort(viewer->window);
// Draw speed box as a popup menu control
GetDItemRect(viewer->window, kPICSViewer_SpeedBox, &frame);
OffsetRect(&frame, 1, 1);
frame.left++;
frame.top++;
FrameRect(&frame);
frame.top--;
frame.left--;
OffsetRect(&frame, -1, -1);
EraseRect(&frame);
FrameRect(&frame);
// Update current frame, speed, etc.
_UpdatePICSViewerInfo(viewer);
NumToString(viewer->picsFrame.right, tempStr);
SetDItemText(viewer->window, kPICSViewer_PICSWidthField, tempStr);
NumToString(viewer->picsFrame.bottom, tempStr);
SetDItemText(viewer->window, kPICSViewer_PICSHeightField, tempStr);
// Background picture of control buttons
PicHandle btnPic;
GetDItemRect(viewer->window, kPICSViewer_BtnBox, &frame);
btnPic = (PicHandle)Get1Resource('PICT', kPICSViewer_ButtonBoxID);
DrawPicture(btnPic, &frame);
ReleaseResource((Handle)btnPic);
// Speed popup menu triangle icon
GetDItemRect(viewer->window, kPICSViewer_SpeedPopupBtn, &frame);
btnPic = (PicHandle)Get1Resource('PICT', kPICSViewer_SpeedPopupID);
DrawPicture(btnPic, &frame);
ReleaseResource((Handle)btnPic);
for (i = kPICSViewer_StopBtn; i <= kPICSViewer_ForwardBtn; i++) {
_DrawPICSViewerBtn(viewer, i, false);
}
/*
// Fill and frame pics play area
RGBColor fillColor = {56797,56797,56797};
RGBColor saveFore;
GetForeColor(&saveFore);
RGBForeColor(&fillColor);
GetDItemRect(viewer->window, kPICSViewer_OutputBox, &frame);
PaintRect(&frame);
frame.left++;
frame.top++;
frame.right -= 2;
frame.bottom -= 2;
fillColor.red = fillColor.green = fillColor.blue = 43690;
RGBForeColor(&fillColor);
// Top
MoveTo(frame.left, frame.top);
LineTo(frame.right, frame.top);
// Left
MoveTo(frame.left, frame.top);
LineTo(frame.left, frame.bottom);
// Top
MoveTo(frame.left, frame.top+1);
LineTo(frame.right, frame.top+1);
// Left
MoveTo(frame.left+1, frame.top);
LineTo(frame.left+1, frame.bottom);
fillColor.red = fillColor.green = fillColor.blue = 65535;
RGBForeColor(&fillColor);
// Right
MoveTo(frame.right, frame.top+1);
LineTo(frame.right, frame.bottom);
// Bottom
MoveTo(frame.left+1, frame.bottom);
MoveTo(frame.right, frame.bottom);
// Right
MoveTo(frame.right-1, frame.top+1);
LineTo(frame.right-1, frame.bottom);
// Bottom
MoveTo(frame.left+1, frame.bottom-1);
LineTo(frame.right, frame.bottom-1);
frame.left--;
frame.top--;
frame.right += 2;
frame.bottom += 2;
fillColor.red = fillColor.green = fillColor.blue = 17476;
RGBForeColor(&fillColor);
FrameRect(&frame);
*/
GetDItemRect(viewer->window, kPICSViewer_OutputBox, &frame);
GrayDrawShadowBox(&frame, NULL);
// Draw lines (dark gray)
for (i = kPICSViewer_Line1; i <= kPICSViewer_Line3; i++) {
GetDItemRect(viewer->window, i, &frame);
GrayDrawShadowLine(&frame, NULL);
}
/*
// Restore original fore color (black)
RGBForeColor(&saveFore);
*/
// Frame border of pics
frame = viewer->outputFrame;
InsetRect(&frame, -1, -1);
GrayDrawShadowBox(&frame, NULL);
// Draw PICS frame
_DrawPICS(viewer);
//_FrameMarquee(viewer);
SetPort(savePort);
UseResFile(oldRefNum);
} // END UpdatePICSViewer
// ---------------------------------------------------------------------------
void _ActivatePICSViewer(PICSViewerData *viewer, Boolean activate) {
GrafPtr savePort;
GetPort(&savePort);
SetPort(viewer->window);
if (!activate)
_EraseMarquee(viewer, NULL);
short hiliteMode;
if (activate)
hiliteMode = 0;
else
hiliteMode = 255;
HiliteControl((ControlHandle)GetDItemHdl(viewer->window,
kPICSViewer_CompositeBtn), hiliteMode);
HiliteControl((ControlHandle)GetDItemHdl(viewer->window,
kPICSViewer_SplitBtn), hiliteMode);
HiliteControl((ControlHandle)GetDItemHdl(viewer->window,
kPICSViewer_TrackMouseBtn), hiliteMode);
HiliteControl((ControlHandle)GetDItemHdl(viewer->window,
kPICSViewer_LoopBtn), hiliteMode);
HiliteControl((ControlHandle)GetDItemHdl(viewer->window,
kPICSViewer_BounceBackBtn), hiliteMode);
if (!activate) {
TextMode(grayishTextOr);
UpdateDialog(viewer->window, viewer->window->visRgn);
}
else {
TextMode(srcOr);
UpdateDialog(viewer->window, viewer->window->visRgn);
}
SetPort(savePort);
} // END _ActivatePICSViewer
// ---------------------------------------------------------------------------
void _UpdatePICSViewerInfo(PICSViewerData *viewer) {
Str15 tempStr;
SetPort(viewer->window);
NumToString(viewer->curFrame+1, tempStr);
SetDItemText(viewer->window, kPICSViewer_CurFrameField, tempStr);
NumToString(viewer->numFrames, tempStr);
SetDItemText(viewer->window, kPICSViewer_NumFramesField, tempStr);
TextFace(bold);
NumToString(viewer->picsInfo.speed, tempStr);
SetDItemText(viewer->window, kPICSViewer_SpeedField, tempStr);
TextFace(0);
} // END _UpdatePICSViewerInfo
// ---------------------------------------------------------------------------
static void _TrackMouseIdle(PICSViewerData *viewer, Point mouseLoc);
void _IdlePICSViewer(PICSViewerData *viewer) {
GrafPtr savePort;
GetPort(&savePort);
SetPort(viewer->window);
if (FrontWindow() == viewer->window) {
if (viewer->trackMouse) {
// Update cursor
Point mouseLoc;
GetMouse(&mouseLoc);
if (!PtInRect(mouseLoc, &viewer->outputFrame)) {
SetCursor(&qd.arrow);
viewer->currentAction = kNoAction;
if (viewer->trackingPoint.h != 0 &&
viewer->trackingPoint.v != 0) {
SetDItemText(viewer->window,
kPICSViewer_TrackMouseField, kEmptyStr);
viewer->trackingPoint.h = 0;
viewer->trackingPoint.v = 0;
}
}
else {
_SetPICSViewerCursor(viewer);
_TrackMouseIdle(viewer, mouseLoc);
}
// Animate current marquee. Cool!
if (!EmptyRect(&viewer->marqueeRect)) {
_FrameMarquee(viewer);
}
}
}
else {
}
SetPort(savePort);
} // END _IdlePICSViewer
void _TrackMouseIdle(PICSViewerData *viewer, Point mouseLoc) {
Str63 outputStr = "\p[ Left: ";
Str15 topStr = "\p | Top: ";
Str15 endStr = "\p ]";
Str15 numStr;
if (!EqualPt(mouseLoc, viewer->trackingPoint)) {
viewer->trackingPoint = mouseLoc;
mouseLoc.h -= viewer->outputFrame.left;
mouseLoc.v -= viewer->outputFrame.top;
NumToString(mouseLoc.h, numStr);
PStrCat(numStr, outputStr);
PStrCat(topStr, outputStr);
NumToString(mouseLoc.v, numStr);
PStrCat(numStr, outputStr);
PStrCat(endStr, outputStr);
SetDItemText(viewer->window, kPICSViewer_TrackMouseField, outputStr);
}
} // END _TrackMouseIdle
// ---------------------------------------------------------------------------
enum {
kAdjustSlackPixels = 3
};
void _SetPICSViewerCursor(PICSViewerData *viewer) {
Point mouseLoc;
GetMouse(&mouseLoc);
if (viewer->trackMouse && !EmptyRect(&viewer->marqueeRect)) {
Rect prelimCheck = viewer->marqueeRect;
InsetRect(&prelimCheck, -kAdjustSlackPixels,
-kAdjustSlackPixels);
if (PtInRect(mouseLoc, &prelimCheck)) {
// Determine whether to adjust selection or not
Rect marquee = viewer->marqueeRect;
if ((mouseLoc.h < marquee.left + kAdjustSlackPixels) &&
(mouseLoc.h > marquee.left - kAdjustSlackPixels)) {
SetCursor(*GetCursor(kHorizontalArrowID));
viewer->currentAction = kLeftAdjustSelectionAction;
}
else if ((mouseLoc.h < marquee.right + kAdjustSlackPixels) &&
(mouseLoc.h > marquee.right - kAdjustSlackPixels)) {
SetCursor(*GetCursor(kHorizontalArrowID));
viewer->currentAction = kRightAdjustSelectionAction;
}
else if ((mouseLoc.v < marquee.top + kAdjustSlackPixels) &&
(mouseLoc.v > marquee.top - kAdjustSlackPixels)) {
SetCursor(*GetCursor(kVerticalArrowID));
viewer->currentAction = kTopAdjustSelectionAction;
}
else if ((mouseLoc.v < marquee.bottom + kAdjustSlackPixels) &&
(mouseLoc.v > marquee.bottom - kAdjustSlackPixels)) {
SetCursor(*GetCursor(kVerticalArrowID));
viewer->currentAction = kBottomAdjustSelectionAction;
}
else if (PtInRect(mouseLoc, &viewer->marqueeRect)) {
/*
if (CROPCLICK_SHORTCUT) {
SetCursor(*GetCursor(kScissorCursorID));
viewer->currentAction = kCompositeAction;
}
*/
if (MOVESELECTION_SHORTCUT) {
SetCursor(*GetCursor(kHandOpenCursorID));
viewer->currentAction = kMoveSelectionAction;
}
else {
SetCursor(*GetCursor(kCrossCursorID));
viewer->currentAction = kSelectionAction;
}
}
else {
SetCursor(*GetCursor(kCrossCursorID));
viewer->currentAction = kSelectionAction;
}
}
else {
SetCursor(*GetCursor(kCrossCursorID));
viewer->currentAction = kSelectionAction;
}
}
else {
if (PtInRect(mouseLoc, &viewer->outputFrame)) {
SetCursor(*GetCursor(kCrossCursorID));
viewer->currentAction = kSelectionAction;
}
else {
SetCursor(&qd.arrow);
viewer->currentAction = kNoAction;
}
}
} // END _SetPICSViewerCursor
// ---------------------------------------------------------------------------
void _CompositePICSViewer(PICSViewerData *viewer) {
FSSpec file;
Rect cropRect;
file = viewer->picsFile;
if (viewer->trackMouse && !EmptyRect(&viewer->marqueeRect)) {
cropRect = viewer->marqueeRect;
OffsetRect(&cropRect, -viewer->outputFrame.left,
-viewer->outputFrame.top);
}
else {
cropRect = viewer->outputFrame;
FlushRectTopLeft(&cropRect);
}
SetupCompositeDialog(&viewer->picsFile, viewer->fileRefNum, &cropRect,
viewer->numFrames);
} // END _CompositePICSViewer
void _SplitPICSViewer(PICSViewerData *viewer) {
SplitPICSFile(kPhotoShopCreatorType, &viewer->picsFile, viewer->fileRefNum);
} // END _SplitPICSViewer
// ---------------------------------------------------------------------------
void _CopyPICSViewerFrame(PICSViewerData *viewer) {
PicHandle picToCopy;
if (!viewer->trackMouse || EmptyRect(&viewer->marqueeRect)) {
// If no marquee selection, copy direct from original
// pict resource
UseResFile(viewer->fileRefNum);
picToCopy = (PicHandle)Get1Resource(kPICSRsrcType,
kPICSRsrcStartID + viewer->curFrame);
if (picToCopy == NULL) {
// ERROR HANDLING
SysBeep(10);
return;
}
UseResFile(sPICSViewer.appFileRefNum);
DetachResource((Handle)picToCopy);
}
else {
// Else copy only a portion of image by capturing
// from offscreen buffer. Result may differ from
// above because depth of buffer may be different
// from depth of original PICT resource
Rect srcRect = viewer->marqueeRect;
OffsetRect(&srcRect, -viewer->outputFrame.left,
-viewer->outputFrame.top);
// Map src rect to correct frame in viewer->buffer
OffsetRect(&srcRect, viewer->curFrame *
viewer->picsFrame.right, 0);
CapturePICT(viewer->buffer, viewer->buffer,
&srcRect, &srcRect, &picToCopy);
}
if (picToCopy != NULL) {
ZeroScrap();
HLock((Handle)picToCopy);
PutScrap(GetHandleSize((Handle)picToCopy),
kPICSRsrcType, (Ptr)*picToCopy);
HUnlock((Handle)picToCopy);
DisposeHandle((Handle)picToCopy);
}
else {
// ERROR HANDLING
SysBeep(10);
}
} // END
// ---------------------------------------------------------------------------
void _RewindPICSViewer(PICSViewerData *viewer) {
viewer->curFrame = 0;
_DrawPICS(viewer);
} // END _RewindPICSViewer
void _StepBackPICSViewer(PICSViewerData *viewer) {
if (viewer->curFrame != 0)
viewer->curFrame--;
_DrawPICS(viewer);
} // END _StepBackPICSViewer
void _StepForwardPICSViewer(PICSViewerData *viewer) {
if (viewer->curFrame !=
viewer->numFrames-1)
viewer->curFrame++;
_DrawPICS(viewer);
} // END _StepForwardPICSViewer
void _ForwardPICSViewer(PICSViewerData *viewer) {
viewer->curFrame = viewer->numFrames-1;
_DrawPICS(viewer);
} // END _ForwardPICSViewer
// ---------------------------------------------------------------------------
void _IncreasePICSViewerSpeed(PICSViewerData *viewer) {
short speedIncrement;
if (!LARGERINCREMENT_SHORTCUT)
speedIncrement = kUsualSpeedIncrement;
else
speedIncrement = kLargerSpeedIncrement;
viewer->picsInfo.speed += speedIncrement;
_UpdatePICSViewerInfo(viewer);
_SetPICSViewerModified(viewer, true);
} // END _IncreasePICSViewerSpeed
void _DecreasePICSViewerSpeed(PICSViewerData *viewer) {
short speedIncrement;
if (!LARGERINCREMENT_SHORTCUT)
speedIncrement = kUsualSpeedIncrement;
else
speedIncrement = kLargerSpeedIncrement;
if (viewer->picsInfo.speed > speedIncrement) {
viewer->picsInfo.speed -= speedIncrement;
_UpdatePICSViewerInfo(viewer);
_SetPICSViewerModified(viewer, true);
}
else {
SysBeep(10);
}
} // END _DescreasePICSViewerSpeed
// ---------------------------------------------------------------------------
void _SetPICSViewerModified(PICSViewerData *viewer, Boolean modified) {
Str255 windName;
Str255 updatedName = "\p√";
if (viewer->fileModified != modified) {
viewer->fileModified = modified;
if (modified) {
GetWTitle(viewer->window, windName);
PStrCat(windName, updatedName);
SetWTitle(viewer->window, updatedName);
}
else {
GetWTitle(viewer->window, windName);
windName[1] = windName[0] - 1;
SetWTitle(viewer->window, &windName[1]);
}
}
} // END _SetPICSViewerModified
Boolean _IsPICSViewerModified(PICSViewerData *viewer) {
return(viewer->fileModified);
} // END _IsPICSViewerModified
// ---------------------------------------------------------------------------
#include "AlphaChannel.h"
void _DrawPICS(PICSViewerData *viewer) {
Rect srcFrame, destFrame;
short transferMode;
RGBColor saveBack, backColor;
GetBackColor(&saveBack);
backColor.red = backColor.green = backColor.blue = 0xFFFF; // White
RGBBackColor(&backColor);
transferMode = GetGraphicsBufferTransferMode();
SetGraphicsBufferTransferMode(srcCopy);
srcFrame = viewer->picsFrame;
OffsetRect(&srcFrame, 0, viewer->curFrame * srcFrame.bottom);
destFrame = viewer->outputFrame;
// An experiment: this will allow you to see the alpha channel
// of a 32-bit PICS file. You will not be able to save it yet.
// Actually, you won't see the alpha channel. Instead, the sprite
// will be masked, and the background will be erased with white.
// Full alpha-channel support will be in the next release.
if (OptionKeyDown()) {
SplitAlphaChannel(
GetGraphicsBufferGWorld(viewer->buffer),
GetGraphicsBufferGWorld(viewer->buffer),
NULL,
NULL);
}
CopyGraphicsBuffer2Window(viewer->buffer,
viewer->window, (CP_Rect*)&srcFrame, (CP_Rect*)&destFrame);
SetGraphicsBufferTransferMode(transferMode);
RGBBackColor(&saveBack);
Str15 tempStr;
NumToString(viewer->curFrame+1, tempStr);
SetDItemText(viewer->window, kPICSViewer_CurFrameField, tempStr);
} // END DrawPICS
// ---------------------------------------------------------------------------
void _PlaySynchPICSViewer(PICSViewerData *viewer) {
long dummy;
Boolean done = false;
Boolean increasingFrame = true;
Boolean drawMarquee;
_DrawPICSViewerBtn(viewer, kPICSViewer_PlayBtn, true);
while(StillDown()) {} // Wait for a mouse-up first.
if (DRAWMARQUEE_SHORTCUT && !EmptyRect(&viewer->marqueeRect))
drawMarquee = true;
else
drawMarquee = false;
if (FASTESTANIM_SHORTCUT)
SetTimerRate(kTimerRateOff);
else
StartTimerFPS(viewer->picsInfo.speed);
do {
if (TimerDoNow()) {
_DrawPICS(viewer);
if (drawMarquee)
_FrameMarquee(viewer);
if (viewer->doLoop) {
if (!viewer->doBounceBack) {
if (viewer->curFrame <
viewer->numFrames-1)
viewer->curFrame++;
else
viewer->curFrame = 0;
}
else {
if (increasingFrame) {
if (viewer->curFrame < viewer->numFrames-1)
viewer->curFrame++;
else {
increasingFrame = false;
viewer->curFrame--;
}
}
else {
if (viewer->curFrame > 0)
viewer->curFrame--;
else {
increasingFrame = true;
viewer->curFrame++;
}
}
}
}
else {
if (viewer->curFrame == viewer->numFrames-1)
done = true;
else
viewer->curFrame++;
}
ResetTimer();
}
if (Button())
done = true;
} while (!done);
_DrawPICS(viewer); // Update one last time to synch curFrame field in
// dlog and current frame in viewer->curFrame
StopTimer();
_DrawPICSViewerBtn(viewer, kPICSViewer_StopBtn, true);
Delay(10, &dummy);
_DrawPICSViewerBtn(viewer, kPICSViewer_StopBtn, false);
_DrawPICSViewerBtn(viewer, kPICSViewer_PlayBtn, false);
FlushEvents(everyEvent, 0);
} // ENd PlaySynchPICSViewer